
import tkinter as tk
from tkinter import messagebox


class PCB:
    def __init__(self, name, priority, run_time):
        self.name = name  # 进程名
        self.priority = priority  # 优先数
        self.run_time = run_time  # 要求运行时间
        self.status = 'R'  # 初始状态为“就绪”
        self.next = None  # 下一个进程的指针


class ProcessScheduler:
    def __init__(self):
        self.queue = None  # 队列初始化为空
        self.completed_queue = []  # 已完成进程的列表

    def insert_process(self, process):
        """按优先数从大到小插入进程"""
        if not self.queue or process.priority > self.queue.priority:
            process.next = self.queue
            self.queue = process
        else:
            current = self.queue
            while current.next and current.next.priority >= process.priority:
                current = current.next
            process.next = current.next
            current.next = process

    def schedule(self):
        """模拟调度过程"""
        if not self.queue:
            return None  # 如果队列为空，返回None表示无进程可以调度

        # 选择队首进程
        process = self.queue
        self.queue = self.queue.next  # 队列头移除选中的进程

        # 模拟进程运行一次
        process.priority -= 1
        process.run_time -= 1

        # 进程状态变化
        if process.run_time == 0:
            process.status = 'E'  # 结束
            self.completed_queue.append(process)
        else:
            process.status = 'R'  # 就绪

        # 如果进程仍然需要执行，重新插入队列
        if process.run_time > 0:
            self.insert_process(process)

        return process

    def get_queue_state(self):
        """获取当前队列状态"""
        processes = []
        current = self.queue
        while current:
            processes.append(f"进程名: {current.name}, 优先数: {current.priority}, "
                             f"要求运行时间: {current.run_time}, 状态: {current.status}")
            current = current.next
        return "\n".join(processes)

    def get_completed_state(self):
        """获取已完成进程状态"""
        processes = []
        for process in self.completed_queue:
            processes.append(f"进程名: {process.name}, 优先数: {process.priority}, "
                             f"要求运行时间: {process.run_time}, 状态: {process.status}")
        return "\n".join(processes)


class SchedulerApp:
    def __init__(self, root):
        self.root = root
        self.root.title("进程调度模拟")

        self.scheduler = ProcessScheduler()

        # 创建界面
        self.create_widgets()

    def create_widgets(self):
        # 左侧未完成进程显示框
        self.left_frame = tk.Frame(self.root)
        self.left_frame.pack(side="left", padx=10, pady=10)

        self.left_label = tk.Label(self.left_frame, text="未完成进程", font=("Arial", 14))
        self.left_label.pack()

        self.left_text = tk.Text(self.left_frame, width=50, height=20)
        self.left_text.pack()

        # 右侧已完成进程显示框
        self.right_frame = tk.Frame(self.root)
        self.right_frame.pack(side="left", padx=10, pady=10)

        self.right_label = tk.Label(self.right_frame, text="已完成进程", font=("Arial", 14))
        self.right_label.pack()

        self.right_text = tk.Text(self.right_frame, width=50, height=20)
        self.right_text.pack()

        # 中间部分: 每次调度的进程和状态变化输出框
        self.middle_frame = tk.Frame(self.root)
        self.middle_frame.pack(side="top", padx=10, pady=10)

        self.schedule_output_label = tk.Label(self.middle_frame, text="每次调度输出", font=("Arial", 14))
        self.schedule_output_label.pack()

        self.schedule_output = tk.Text(self.middle_frame, width=100, height=10)
        self.schedule_output.pack()

        # 按钮和信息框
        self.control_frame = tk.Frame(self.root)
        self.control_frame.pack(side="bottom", pady=10)

        self.schedule_button = tk.Button(self.control_frame, text="执行一次调度", command=self.schedule_process)
        self.schedule_button.pack()

        # 输入框和标签
        self.input_frame = tk.Frame(self.root)
        self.input_frame.pack(side="bottom", pady=10)

        self.name_label = tk.Label(self.input_frame, text="进程名称:")
        self.name_label.grid(row=0, column=0, padx=10)

        self.name_entry = tk.Entry(self.input_frame)
        self.name_entry.grid(row=0, column=1, padx=10)

        self.priority_label = tk.Label(self.input_frame, text="优先级:")
        self.priority_label.grid(row=1, column=0, padx=10)

        self.priority_entry = tk.Entry(self.input_frame)
        self.priority_entry.grid(row=1, column=1, padx=10)

        self.run_time_label = tk.Label(self.input_frame, text="要求运行时间:")
        self.run_time_label.grid(row=2, column=0, padx=10)

        self.run_time_entry = tk.Entry(self.input_frame)
        self.run_time_entry.grid(row=2, column=1, padx=10)

        self.add_process_button = tk.Button(self.input_frame, text="添加进程", command=self.add_process)
        self.add_process_button.grid(row=3, columnspan=2, pady=10)

    def add_process(self):
        """添加进程"""
        try:
            name = self.name_entry.get()
            priority = int(self.priority_entry.get())
            run_time = int(self.run_time_entry.get())

            if not name:
                messagebox.showerror("输入错误", "进程名称不能为空")
                return

            # 创建进程对象并插入调度队列
            process = PCB(name, priority, run_time)
            self.scheduler.insert_process(process)

            # 清空输入框
            self.name_entry.delete(0, tk.END)
            self.priority_entry.delete(0, tk.END)
            self.run_time_entry.delete(0, tk.END)

            self.update_display()
        except ValueError:
            messagebox.showerror("输入错误", "请输入有效的数字")

    def schedule_process(self):
        """执行调度"""
        process = self.scheduler.schedule()
        if process:
            self.update_display()

            # 显示调度的进程及其执行后的状态变化
            schedule_info = f"\n调度选择进程: {process.name}\n"
            schedule_info += f"进程 {process.name} 执行后状态变化:\n"
            schedule_info += f"优先数: {process.priority}, 要求运行时间: {process.run_time}, 状态: {process.status}\n"
            self.schedule_output.insert(tk.END, schedule_info)
        else:
            messagebox.showinfo("调度结束", "所有进程已执行完毕")

    def update_display(self):
        """更新显示"""
        self.left_text.delete(1.0, tk.END)
        self.right_text.delete(1.0, tk.END)

        # 显示未完成进程队列
        self.left_text.insert(tk.END, self.scheduler.get_queue_state())

        # 显示已完成进程队列
        self.right_text.insert(tk.END, self.scheduler.get_completed_state())


if __name__ == "__main__":
    root = tk.Tk()
    app = SchedulerApp(root)
    root.mainloop()
